Integrate objects
* Use all features so can pass object to P3

Assign Cell cycle scores * Can compare assignment to individual run assignments

Run SCTransform on individual objects
* regress - Cell cycle + noregress + regress.CC - regress on cell cycle - probably not the best option as it removes any cell cycle information that may be important for differentiating cells + regress.diff - regress on the difference in cell cycle values; per Seurat notations, it preserves cell cycle information relevant to development * regress - other features + nCounts_RNA + percent.mt

Cluster & Plot!

Save each object to a separate file

importDate - select the creation date for the desired object

Set up libraries and directories

Plot Counts Comparisons

Normalize & Scale

Use SCTransform with regression options noted Calculate pca and umap

Preserve all features for Precepts compatibility

Optionally Plot Missing Features

Note that features present in <= 4 cells do not make it through SCTransform

Cluster the individual runs

Note: Ran individual PCA/UMAP on a subset of genes in 1a.
Run here on all genes? Not sure that this will substantially change anything.

Preliminary Cluster ID

Integrate the objects

Preserve as many features as possible in the integrated object

Optionally Plot Missing Features

Lose ~2500 features (of 16990) during integration

Plot UMAP and PCA

15:02:27 UMAP embedding parameters a = 0.9922 b = 1.112
15:02:27 Read 1657 rows and found 30 numeric columns
15:02:27 Using Annoy for neighbor search, n_neighbors = 30
15:02:27 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:02:28 Writing NN index file to temp file /var/folders/qm/j2npc7ss1bv_6ks_fh41llp0yk4_ps/T//RtmpguGud9/file1601f4df52f40
15:02:28 Searching Annoy index using 1 thread, search_k = 3000
15:02:28 Annoy recall = 100%
15:02:28 Commencing smooth kNN distance calibration using 1 thread
15:02:29 Initializing from normalized Laplacian + noise
15:02:29 Commencing optimization for 500 epochs, with 66338 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:02:32 Optimization finished
15:04:39 UMAP embedding parameters a = 0.9922 b = 1.112
15:04:39 Read 2754 rows and found 30 numeric columns
15:04:39 Using Annoy for neighbor search, n_neighbors = 30
15:04:39 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:04:39 Writing NN index file to temp file /var/folders/qm/j2npc7ss1bv_6ks_fh41llp0yk4_ps/T//RtmpguGud9/file1601f1bf13abc
15:04:39 Searching Annoy index using 1 thread, search_k = 3000
15:04:40 Annoy recall = 100%
15:04:40 Commencing smooth kNN distance calibration using 1 thread
15:04:41 Initializing from normalized Laplacian + noise
15:04:41 Commencing optimization for 500 epochs, with 113294 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:04:47 Optimization finished
15:07:51 UMAP embedding parameters a = 0.9922 b = 1.112
15:07:51 Read 3404 rows and found 30 numeric columns
15:07:51 Using Annoy for neighbor search, n_neighbors = 30
15:07:51 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:07:51 Writing NN index file to temp file /var/folders/qm/j2npc7ss1bv_6ks_fh41llp0yk4_ps/T//RtmpguGud9/file1601f7a471af8
15:07:51 Searching Annoy index using 1 thread, search_k = 3000
15:07:52 Annoy recall = 100%
15:07:53 Commencing smooth kNN distance calibration using 1 thread
15:07:54 Initializing from normalized Laplacian + noise
15:07:54 Commencing optimization for 500 epochs, with 140766 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:08:00 Optimization finished
15:09:42 UMAP embedding parameters a = 0.9922 b = 1.112
15:09:42 Read 1873 rows and found 30 numeric columns
15:09:42 Using Annoy for neighbor search, n_neighbors = 30
15:09:42 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:09:43 Writing NN index file to temp file /var/folders/qm/j2npc7ss1bv_6ks_fh41llp0yk4_ps/T//RtmpguGud9/file1601f523bce7f
15:09:43 Searching Annoy index using 1 thread, search_k = 3000
15:09:44 Annoy recall = 100%
15:09:44 Commencing smooth kNN distance calibration using 1 thread
15:09:45 Initializing from normalized Laplacian + noise
15:09:45 Commencing optimization for 500 epochs, with 76218 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
15:09:49 Optimization finished

Save the data

Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 1657
Number of edges: 69751

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.7643
Number of communities: 8
Elapsed time: 0 seconds
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 2754
Number of edges: 113800

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.7809
Number of communities: 10
Elapsed time: 0 seconds
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 3404
Number of edges: 139696

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.7827
Number of communities: 11
Elapsed time: 0 seconds
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck

Number of nodes: 1873
Number of edges: 91025

Running Louvain algorithm...
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Maximum modularity in 10 random starts: 0.7090
Number of communities: 9
Elapsed time: 0 seconds
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|

Error: Cannot find 'pca' in this Seurat object
LS0tCnRpdGxlOiAiQU1MLUVUTyBTTyAtIGludGVncmF0ZSwgc2N0LCBjbHVzdGVyIgphdXRob3I6ICJUTHVzYXJkaSIKZGF0ZTogIjExLzA1LzIwMjAiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHllcwogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKcGFyYW1zOgogIGxvY2FsOiBUUlVFCi0tLQoKSW50ZWdyYXRlIG9iamVjdHMgICAKKiBVc2UgYWxsIGZlYXR1cmVzIHNvIGNhbiBwYXNzIG9iamVjdCB0byBQMwoKQXNzaWduIENlbGwgY3ljbGUgc2NvcmVzCiogQ2FuIGNvbXBhcmUgYXNzaWdubWVudCB0byBpbmRpdmlkdWFsIHJ1biBhc3NpZ25tZW50cwoKUnVuIFNDVHJhbnNmb3JtIG9uIGluZGl2aWR1YWwgb2JqZWN0cyAgIAoqIHJlZ3Jlc3MgLSBDZWxsIGN5Y2xlCiAgKyBub3JlZ3Jlc3MKICArIHJlZ3Jlc3MuQ0MgLSByZWdyZXNzIG9uIGNlbGwgY3ljbGUgLSBwcm9iYWJseSBub3QgdGhlIGJlc3Qgb3B0aW9uIGFzIGl0IHJlbW92ZXMgYW55IGNlbGwgY3ljbGUgaW5mb3JtYXRpb24gdGhhdCBtYXkgYmUgaW1wb3J0YW50IGZvciBkaWZmZXJlbnRpYXRpbmcgY2VsbHMKICArIHJlZ3Jlc3MuZGlmZiAtIHJlZ3Jlc3Mgb24gdGhlIGRpZmZlcmVuY2UgaW4gY2VsbCBjeWNsZSB2YWx1ZXM7IHBlciBTZXVyYXQgbm90YXRpb25zLCBpdCBwcmVzZXJ2ZXMgY2VsbCBjeWNsZSBpbmZvcm1hdGlvbiByZWxldmFudCB0byBkZXZlbG9wbWVudAoqIHJlZ3Jlc3MgLSBvdGhlciBmZWF0dXJlcwogICsgbkNvdW50c19STkEgKyBwZXJjZW50Lm10CiAgCkNsdXN0ZXIgJiBQbG90IQoKU2F2ZSBlYWNoIG9iamVjdCB0byBhIHNlcGFyYXRlIGZpbGUKCmltcG9ydERhdGUgLSBzZWxlY3QgdGhlIGNyZWF0aW9uIGRhdGUgZm9yIHRoZSBkZXNpcmVkIG9iamVjdAogIAojIyMgU2V0IHVwIGxpYnJhcmllcyBhbmQgZGlyZWN0b3JpZXMKCmBgYHtyICJzZXR1cF9saWJzIiwgaW5jbHVkZT1GQUxTRX0KI2tuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KG5ldHdvcmtEMykKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoZHBseXIpCgpydW5zMnByb2Nlc3MgPSBjKCJkbXNvIiwgImF2YSIsICJvcnkiLCAiY29tYm8iKQpiYXNlbGluZSA9ICJkbXNvIgppbXBvcnREYXRlIDwtICIyMDIxLTAxLTA1IgpgYGAKCmBgYHtyICJzZXR1cF92YXJzIiwgaW5jbHVkZT1GQUxTRX0KZGlyZWN0b3J5ID0gbGlzdChyYXcgPSAiL1VzZXJzL2x1c2FyZGkvRG9jdW1lbnRzL0NFREFSL1Byb2plY3RzLzMuQVNYTF9tdXRhbnQvMS5BTUxfRVRPL2FuYWx5c2lzL2RhdGEvcmF3IiwKICAgICAgICAgICAgICAgICByZGEgPSAiL1VzZXJzL2x1c2FyZGkvRG9jdW1lbnRzL0NFREFSL1Byb2plY3RzLzMuQVNYTF9tdXRhbnQvMS5BTUxfRVRPL2FuYWx5c2lzL2RhdGEvcmRhIikKCmV4cHRzLmxzIDwtIHJlYWRSRFMoc3ByaW50ZigiJXMvYW1sX2V0by5wcmVwcm9jU08ubm9maWx0LiVzLnJkcyIsIGRpcmVjdG9yeSRyZGEsIGltcG9ydERhdGUpKQpgYGAKCiMjIyBQbG90IENvdW50cyBDb21wYXJpc29ucwoKYGBge3IsIGVjaG89RkFMU0V9CnBsb3RTZXQgPSBsaXN0KGRtc28gPSBsaXN0KGNvbCA9ICIjZTQxYTFjIiwgbHR5ID0gMSksCiAgICAgICAgICAgICAgIGF2YSA9IGxpc3QoY29sID0gIiMzNzdlYjgiLCBsdHkgPSAxKSwKICAgICAgICAgICAgICAgb3J5ID0gbGlzdChjb2wgPSAiIzRkYWY0YSIsIGx0eSA9IDEpLAogICAgICAgICAgICAgICBjb21ibyA9IGxpc3QoY29sID0gIiNhZGFmNGEiLCBsdHkgPSAxKSkKcnVucyA8LSBuYW1lcyhleHB0cy5scykKCnBsb3RGZWF0dXJlcyA8LSBjKCJuQ291bnRfUk5BIiwgIm5GZWF0dXJlX1JOQSIpCmZvciAobXlmZWF0dXJlIGluIHBsb3RGZWF0dXJlcykgewogICMgU2V0IHVwIERlbnNpdHkgUGxvdAogIG1heERlbnMgPC0gMAogIG1heEN0cyA8LSAwCiAgZm9yIChteXJ1biBpbiBuYW1lcyhleHB0cy5scykpIHsKICAgIG15ZGVucyA8LSBkZW5zaXR5KGV4cHRzLmxzW1tteXJ1bl1dQG1ldGEuZGF0YVtbbXlmZWF0dXJlXV0pCiAgICBtYXhEZW5zIDwtIG1heChtYXhEZW5zLCBteWRlbnMkeSkKICAgIG1heFBjdCA8LSAxCiAgICBtYXhDdHMgPC0gbWF4KG1heEN0cywgZXhwdHMubHNbW215cnVuXV1AbWV0YS5kYXRhW1tteWZlYXR1cmVdXSkKICB9CgogICMgQ3JlYXRlIGEgcGxvdCBwYW5lCiAgcGxvdChOVUxMLCB4bGltPWMoMCwgbWF4Q3RzKSwgeWxpbSA9IGMoMCwgbWF4RGVucyksIAogICAgICAgeGxhYiA9IHNwcmludGYoIiVzIiwgbXlmZWF0dXJlKSwKICAgICAgIHlsYWIgPSAiRGVuc2l0eSIsIGxhcyA9IDEsCiAgICAgICBtYWluID0gc3ByaW50ZigiRGlzdHJpYnV0aW9uIG9mICVzIHBlciBDZWxsIGJ5IEV4cGVyaW1lbnQiLCBteWZlYXR1cmUpKQogIGFibGluZShoID0gMCwgY29sID0gImdyZXk4MCIpCgogICMgQWRkIGEgbGVnZW5kCiAgbGVnZW5kKHg9InRvcHJpZ2h0IiwgbGVnZW5kID0gcnVucywgbHdkID0gMiwKICAgICAgICAgY29sID0gdW5saXN0KHBsb3RTZXQpW3Bhc3RlKHJ1bnMsICJjb2wiLCBzZXAgPSAiLiIpXSwKICAgICAgICAgbHR5ID0gYXMubnVtZXJpYyh1bmxpc3QocGxvdFNldClbcGFzdGUocnVucywgImx0eSIsIHNlcCA9ICIuIildKSkKCiAgIyBQbG90IGVhY2ggZGVuc2l0eSBsaW5lCiAgZm9yIChteXJ1biBpbiBuYW1lcyhleHB0cy5scykpIHsKICAgIGxpbmVzKGRlbnNpdHkoZXhwdHMubHNbW215cnVuXV1AbWV0YS5kYXRhW1tteWZlYXR1cmVdXSksIGNvbCA9IHBsb3RTZXRbW215cnVuXV0kY29sLAogICAgICAgICAgbHdkID0gMikKICB9Cn0KYGBgCgojIyMgTm9ybWFsaXplICYgU2NhbGUKVXNlIFNDVHJhbnNmb3JtIHdpdGggcmVncmVzc2lvbiBvcHRpb25zIG5vdGVkCkNhbGN1bGF0ZSBwY2EgYW5kIHVtYXAgCgpQcmVzZXJ2ZSBhbGwgZmVhdHVyZXMgZm9yIFByZWNlcHRzIGNvbXBhdGliaWxpdHkKCmBgYHtyLCAicnVuU0NUIiwgd2FybmluZz1GQUxTRSwgZWNobz1GQUxTRX0KcmVncmVzc2lvbnMgPC0gbGlzdChub3JlZ3Jlc3Npb24gPSAiTlVMTCIsCiAgICAgICAgICAgICAgICAgICAgcmVncmVzcy5DQyA9IGMoIlMuU2NvcmUiLCAiRzJNLlNjb3JlIiksCiAgICAgICAgICAgICAgICAgICAgcmVncmVzcy5EaWZmID0gYygiQ0MuRGlmZmVyZW5jZSIpKSAgICAKcmVncmVzc2lvbjJ1c2UgPC0gInJlZ3Jlc3MuRGlmZiIKCmZvciAobXlyZWdyZXNzIGluIHJlZ3Jlc3Npb24ydXNlKSB7CiAgZm9yIChteXJ1biBpbiBuYW1lcyhleHB0cy5scykpIHsKICAgIG15c28gPC0gZXhwdHMubHNbW215cnVuXV0KICAgIGlmIChteXJlZ3Jlc3MgPT0gIm5vcmVncmVzc2lvbiIpIHsKICAgICAgbXlhc3NheSA8LSAiU0NUIgogICAgICBteXNvIDwtIFNDVHJhbnNmb3JtKG15c28sIHZlcmJvc2UgPSBGQUxTRSwgbmV3LmFzc2F5Lm5hbWUgPSBteWFzc2F5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUuZmVhdHVyZXMubiA9IG5yb3cobXlzb0Bhc3NheXMkUk5BQGNvdW50cykpCiAgICB9IGVsc2UgewogICAgICBteWFzc2F5IDwtIGdzdWIoInJlZ3Jlc3MiLCAiU0NUIiwgbXlyZWdyZXNzKQogICAgICBteXNvIDwtIFNDVHJhbnNmb3JtKG15c28sIHZlcmJvc2UgPSBGQUxTRSwgbmV3LmFzc2F5Lm5hbWUgPSBteWFzc2F5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFycy50by5yZWdyZXNzID0gcmVncmVzc2lvbnNbW215cmVncmVzc11dLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyaWFibGUuZmVhdHVyZXMubiA9IG5yb3cobXlzb0Bhc3NheXMkUk5BQGNvdW50cykpCiAgICB9CiAgICAKICAgICMgQ2FsY3VsYXRlIHBjYQogICAgbXlwY2EgPC0gZ3N1YigiU0NUIiwgInBjYSIsIG15YXNzYXkpCiAgICBteXBjYWtleSA8LSBwYXN0ZShnc3ViKCIvLiIsICIiLCBteXBjYSksICJfIiwgc2VwID0gIiIpCiAgICBteXNvIDwtIFJ1blBDQShteXNvLCB2ZXJib3NlID0gRkFMU0UsIGFzc2F5ID0gbXlhc3NheSwKICAgICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uLm5hbWUgPSBteXBjYSwgcmVkdWN0aW9uLmtleSA9IG15cGNha2V5KQogICAgICAKICAgICMgQ3JlYXRlIHVtYXAKICAgIG15dW1hcCA8LSBnc3ViKCJwY2EiLCAidW1hcCIsIG15cGNhKQogICAgbXl1bWFwa2V5IDwtIHBhc3RlKGdzdWIoIi8uIiwgIiIsIG15dW1hcCksICJfIiwgc2VwID0gIiIpCiAgICBteXNvIDwtIFJ1blVNQVAobXlzbywgZGltcyA9IDE6MzAsIGFzc2F5ID0gbXlhc3NheSwKICAgICAgICAgICAgICAgICAgICAgIHJlZHVjdGlvbiA9IG15cGNhLCByZWR1Y3Rpb24ubmFtZSA9IG15dW1hcCwgcmVkdWN0aW9uLmtleSA9IG15dW1hcGtleSkKICAgIAogICAgZXhwdHMubHNbW215cnVuXV0gPC0gbXlzbwogIH0gCn0KYGBgCgojIyMgT3B0aW9uYWxseSBQbG90IE1pc3NpbmcgRmVhdHVyZXMKTm90ZSB0aGF0IGZlYXR1cmVzIHByZXNlbnQgaW4gPD0gNCBjZWxscyBkbyBub3QgbWFrZSBpdCB0aHJvdWdoIFNDVHJhbnNmb3JtCgpgYGB7ciwgInBsb3RtaXNzaW5nZmVhdCIsZWNobz1GQUxTRX0KaWYgKFRSVUUpIHsKICBmb3IgKG15cnVuIGluIG5hbWVzKGV4cHRzLmxzKSkgewogICAgbXlzbyA8LSBleHB0cy5sc1tbbXlydW5dXQogICAgbG9zdEZlYXQgPC0gcm93bmFtZXMobXlzb0Bhc3NheXMkUk5BQGNvdW50cylbIShyb3duYW1lcyhteXNvQGFzc2F5cyRSTkFAY291bnRzKSAlaW4lIHJvd25hbWVzKG15c29AYXNzYXlzJFNDVC5EaWZmQGNvdW50cykpXQogICAgY291bnRzLnBlci5mZWF0IDwtIGFwcGx5KG15c29AYXNzYXlzJFJOQUBjb3VudHMsIDEsIHN1bSkKICAgIGNlbGxzLnBlci5mZWF0IDwtIE1hdHJpeDo6cm93U3VtcyhteXNvQGFzc2F5cyRSTkFAY291bnRzID4gMCkKICAgIAogICAgIyBQbG90IGNvdW50cyBhbmQgY2VsbHMgCiAgICBwbG90KHggPSBsb2cyKGNvdW50cy5wZXIuZmVhdCksIHkgPSBsb2cyKGNlbGxzLnBlci5mZWF0KSwgcGNoID0gMjAsIGNleCA9IDAuNSkKICAgIHBvaW50cyh4ID0gbG9nMihjb3VudHMucGVyLmZlYXRbbG9zdEZlYXRdKSwgeSA9IGxvZzIoY2VsbHMucGVyLmZlYXRbbG9zdEZlYXRdKSwgcGNoID0gMjAsIGNleCA9IDAuNSwgY29sID0gInJlZCIpCiAgfQp9CmBgYAoKIyMjIENsdXN0ZXIgdGhlIGluZGl2aWR1YWwgcnVucwpOb3RlOiBSYW4gaW5kaXZpZHVhbCBQQ0EvVU1BUCBvbiBhIHN1YnNldCBvZiBnZW5lcyBpbiAxYS4gICAgClJ1biBoZXJlIG9uIGFsbCBnZW5lcz8gTm90IHN1cmUgdGhhdCB0aGlzIHdpbGwgc3Vic3RhbnRpYWxseSBjaGFuZ2UgYW55dGhpbmcuCgpgYGB7ciwgImlDbHVzdGVyIiwgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZm9yIChteXJ1biBpbiBuYW1lcyhleHB0cy5scykpIHsKICBteXNvIDwtIGV4cHRzLmxzW1tteXJ1bl1dCiAgCiAgZm9yIChteXJlZ3Jlc3MgaW4gcmVncmVzc2lvbjJ1c2UpIHsKICAgIG15YXNzYXkgPC0gZ3N1YigicmVncmVzcyIsICJTQ1QiLCBteXJlZ3Jlc3MpCiAgICBteXBjYSA8LSBnc3ViKCJyZWdyZXNzIiwgInBjYS5TQ1QiLCBteXJlZ3Jlc3MpCiAgICBteXBjYV9rZXkgPC0gZ3N1YigicmVncmVzcyIsICJwY2FTQ1RfIiwgbXlyZWdyZXNzKQogICAgbXlmZWF0dXJlcyA8LSByb3duYW1lcyhteXNvQGFzc2F5c1tbbXlhc3NheV1dKQogICAgbXl1bWFwIDwtIGdzdWIoInBjYSIsICJ1bWFwIiwgbXlwY2EpCiAgICAKICAgICMgUGVyZm9ybSBQQ0Egb24gYWxsIGZlYXR1cmVzIChub3RlIHRoYXQgbm9uLXZhcmlhYmxlIGZlYXR1cmVzIHdpbGwgYmUgZHJvcHBlZCkKICAgIG15c28gPC0gUnVuUENBKG15c28sIGFzc2F5ID0gbXlhc3NheSwgZmVhdHVyZXMgPSBteWZlYXR1cmVzLAogICAgICAgICAgICAgICAgICAgcmVkdWN0aW9uLm5hbWUgPSBteXBjYSwgcmVkdWN0aW9uLmtleSA9IG15cGNhX2tleSkKICAgIAogICAgbXlwbG90IDwtIEVsYm93UGxvdChteXNvLCByZWR1Y3Rpb24gPSBteXBjYSwgbmRpbXMgPSA1MCkKICAgIHBsb3QobXlwbG90ICsgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gbXlydW4sIHN1YnRpdGxlID0gbXlyZWdyZXNzKSkKICAgIERpbUhlYXRtYXAobXlzbywgcmVkdWN0aW9uID0gbXlwY2EsIGRpbXMgPSAxOjE1LCBjZWxscyA9IDUwMCwgYmFsYW5jZWQgPSBUUlVFKQogIAogICAgbXlzbyA8LSBGaW5kTmVpZ2hib3JzKG15c28sIGRpbXMgPSAxOjUwLCBhc3NheSA9IG15YXNzYXksIHJlZHVjdGlvbiA9IG15cGNhKQogICAgbXlncmFwaCA8LSBwYXN0ZShteWFzc2F5LCAic25uIiwgc2VwID0gIl8iKQogICAgbXlzbyA8LSBGaW5kQ2x1c3RlcnMobXlzbywgZ3JhcGgubmFtZSA9IG15Z3JhcGgsIHJlc29sdXRpb24gPSAwLjgpCiAgICAKICAgICMgQ3JlYXRlIFVNQVAKICAgIG15c28gPC0gUnVuVU1BUChteXNvLCByZWR1Y3Rpb24gPSBteXBjYSwgZGltcyA9IDE6NTAscmVkdWN0aW9uLm5hbWUgPSBteXVtYXApCiAgICBteXBsb3QgPC0gRGltUGxvdChteXNvLCByZWR1Y3Rpb24gPSBteXVtYXApCiAgICBwbG90KG15cGxvdCArIHBsb3RfYW5ub3RhdGlvbih0aXRsZSA9IG15cnVuLCBzdWJ0aXRsZSA9IG15cmVncmVzcykpCiAgfQogIGV4cHRzLmxzW1tteXJ1bl1dIDwtIG15c28KfQpgYGAKCiMjIyBQcmVsaW1pbmFyeSBDbHVzdGVyIElECgpgYGB7ciwgInByZWxpbUNsdXN0ZXJJRCIsIGVjaG89RkFMU0V9Cm1hcmtlcnMgPC0gbGlzdChlYXJseSA9IGMoIlNPWDQiKSwKICAgICAgICAgICAgICAgIG1pZCA9IGMoIkNFQlBEIiksCiAgICAgICAgICAgICAgICBsYXRlID0gYygiQ0QxNCIpKQoKZm9yIChteXJ1biBpbiBydW5zMnByb2Nlc3MpIHsKICBteXNvIDwtIGV4cHRzLmxzW1tteXJ1bl1dCiAgCiAgZm9yIChteW1hcmtlcnMgaW4gbmFtZXMobWFya2VycykpIHsKICAgIG15cGxvdCA8LSBGZWF0dXJlUGxvdChteXNvLCBmZWF0dXJlcyA9IG1hcmtlcnNbW215bWFya2Vyc11dLCBsYWJlbCA9IFRSVUUsIGxhYmVsLnNpemUgPSA1KQogICAgcGxvdChteXBsb3QgKyBwbG90X2Fubm90YXRpb24odGl0bGUgPSBteXJ1biwgc3VidGl0bGUgPSBteW1hcmtlcnMpKQogIH0KfQoKIyBBc3NpZ24gbGFiZWxzIHRvIERNU08KIyBDbHVzdGVyIExhYmVscwpMYWJlbHMubHMgPC0gbGlzdChkbXNvID0gYyhTQ1QuRGlmZl8wID0gImVhcmx5XzEiLCBTQ1QuRGlmZl8xID0gImxhdGVfMiIsIFNDVC5EaWZmXzIgPSAibWlkXzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBTQ1QuRGlmZl8zID0gImxvbmVfMiIsIFNDVC5EaWZmXzQgPSAibG9uZV8zIiwgU0NULkRpZmZfNSA9ICJsYXRlXzEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBTQ1QuRGlmZl82ID0gImxvbmVfMSIsIFNDVC5EaWZmXzcgPSAibG9uZV80IiksCiAgICAgICAgICAgICAgICAgIGF2YSA9IGMoU0NULkRpZmZfMCA9ICJsYXRlXzIiLCBTQ1QuRGlmZl8xID0gImVhcmx5XzEiLCBTQ1QuRGlmZl8yID0gIm1pZF8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBTQ1QuRGlmZl8zID0gImVhcmx5XzIiLCBTQ1QuRGlmZl80ID0gImxvbmVfMiIsIFNDVC5EaWZmXzUgPSAibGF0ZV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBTQ1QuRGlmZl82ID0gImxvbmVfNSIsIFNDVC5EaWZmXzcgPSAibG9uZV8xIiwgU0NULkRpZmZfOCA9ICJsb25lXzMiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFNDVC5EaWZmXzkgPSAibG9uZV80IiksCiAgICAgICAgICAgICAgICAgIG9yeSA9IGMoU0NULkRpZmZfMCA9ICJsYXRlXzEiLCBTQ1QuRGlmZl8xID0gImVhcmx5XzEiLCBTQ1QuRGlmZl8yID0gImVhcmx5XzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFNDVC5EaWZmXzMgPSAibWlkXzEiLCBTQ1QuRGlmZl80ID0gIm1pZF8yIiwgU0NULkRpZmZfNSA9ICJsYXRlXzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFNDVC5EaWZmXzYgPSAibG9uZV8xIiwgU0NULkRpZmZfNyA9ICJsb25lXzMiLCBTQ1QuRGlmZl84ID0gImxvbmVfMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgU0NULkRpZmZfOSA9ICJsb25lXzQiLCBTQ1QuRGlmZl8xMCA9ICJsb25lXzUiKSwKICAgICAgICAgICAgICAgICAgY29tYm8gPSBjKFNDVC5EaWZmXzAgPSAiZWFybHlfMSIsIFNDVC5EaWZmXzEgPSAibGF0ZV8yIiwgU0NULkRpZmZfMiA9ICJtaWRfMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTQ1QuRGlmZl8zID0gImxhdGVfMSIsIFNDVC5EaWZmXzQgPSAiZWFybHlfMiIsIFNDVC5EaWZmXzUgPSAibG9uZV8xIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNDVC5EaWZmXzYgPSAibG9uZV8yIiwgU0NULkRpZmZfNyA9ICJsb25lXzMiLCBTQ1QuRGlmZl84ID0gImxvbmVfNCIpKQpsYWJlbF9vcmRlciA8LSBjKCJlYXJseV8xIiwgImVhcmx5XzIiLCAibWlkXzEiLCAibWlkXzIiLCAibGF0ZV8xIiwgImxhdGVfMiIsCiAgICAgICAgICAgICAgICAgImxvbmVfMSIsICJsb25lXzIiLCAibG9uZV8zIiwgImxvbmVfNCIsICJsb25lXzUiKQoKIyBSZW5hbWUgQ2x1c3RlcnMgCiMgVGhpcyBjb3VsZCBiZSBtb3JlIGVsZWdhbnQuLi4gIEknbSBtYWtpbmcgbG90cyBvZiBhc3N1bXB0aW9ucwpjb2xvcnMgPC0gYygnI2E2Y2VlMycsJyMxZjc4YjQnLCcjYjJkZjhhJywnIzMzYTAyYycsJyNmYjlhOTknLCcjZTMxYTFjJywnI2ZkYmY2ZicsJyNmZjdmMDAnLCcjY2FiMmQ2JywnIzZhM2Q5YScsJyNmZmZmOTknLCcjYjE1OTI4JykKbmFtZXMoY29sb3JzKSA8LSBsYWJlbF9vcmRlcgoKZm9yIChteXJlZ3Jlc3MgaW4gcmVncmVzc2lvbjJ1c2UpIHsKICBmb3IgKG15cnVuIGluIHJ1bnMycHJvY2VzcykgewogICAgbXlzbyA8LSBleHB0cy5sc1tbbXlydW5dXQogICAgbXlub3JtIDwtIGdzdWIoInJlZ3Jlc3MiLCAiU0NUIiwgbXlyZWdyZXNzKQogICAgCiAgICAjIENyZWF0ZSBhIG5hbWVkIGNvbHVtbgogICAgbXlJZHhuYW1lIDwtIHBhc3RlKG15bm9ybSwgImNsdXN0ZXJJZHgiLCBzZXAgPSAiXyIpCiAgICBteXNvQG1ldGEuZGF0YVtbbXlJZHhuYW1lXV0gPC0gcGFzdGUobXlub3JtLCBteXNvQG1ldGEuZGF0YSRTQ1QuRGlmZl9zbm5fcmVzLjAuOCwgc2VwID0gIl8iKQogICAgCiAgICAjIENyZWF0ZSBhIGxhYmVsZWQgY29sdW1uIChtYWtlIGl0IGEgZmFjdG9yIGZvciBlYXNlIG9mIHJlYWRpbmcpCiAgICBteUlEbmFtZSA8LSBwYXN0ZShteW5vcm0sICJjbHVzdGVySUQiLCBzZXAgPSAiXyIpCiAgICBteXNvQG1ldGEuZGF0YVtbbXlJRG5hbWVdXSA8LSBmYWN0b3IoTGFiZWxzLmxzW1tteXJ1bl1dW215c29AbWV0YS5kYXRhW1tteUlkeG5hbWVdXV0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IGxhYmVsX29yZGVyLCBvcmRlcmVkID0gVFJVRSkKICAgIAogICAgcGxvdGNvbG9ycyA8LSBjb2xvcnNbdW5pcXVlKGxldmVscyhteXNvQG1ldGEuZGF0YVtbbXlJRG5hbWVdXSkpXQogICAgbXlwbG90IDwtIERpbVBsb3QobXlzbywgcmVkdWN0aW9uID0gbXl1bWFwLCBncm91cC5ieSA9IG15SURuYW1lLCBjb2xzID0gcGxvdGNvbG9ycykKICAgIHBsb3QobXlwbG90ICsgcGxvdF9hbm5vdGF0aW9uKHRpdGxlID0gbXlydW4sIHN1YnRpdGxlID0gbXlub3JtKSkKICAgIAogICAgZXhwdHMubHNbW215cnVuXV0gPC0gbXlzbwogIH0KfQpgYGAKCiMjIyBJbnRlZ3JhdGUgdGhlIG9iamVjdHMKUHJlc2VydmUgYXMgbWFueSBmZWF0dXJlcyBhcyBwb3NzaWJsZSBpbiB0aGUgaW50ZWdyYXRlZCBvYmplY3QKCmBgYHtyLCAiaW50ZWdyYXRlIiwgZWNobz1GQUxTRX0KIyBOZWVkZWQgdG8gYXZvaWQgZXJyb3IgaW4gZ2V0R2xvYmFsc2FuZFBhY2thZ2VzIApvcHRpb25zKGZ1dHVyZS5nbG9iYWxzLm1heFNpemU9IDM1MzAqMTAyNF4yKQoKIyBDb3VudCB0aGUgbnVtYmVyIG9mIHVuaXF1ZSBmZWF0dXJlcyBwZXIgZXhwZXJpbWVudAphbGxGZWF0dXJlcyA8LSBOVUxMCmZvciAobXlydW4gaW4gbmFtZXMoZXhwdHMubHMpKSB7CiAgYWxsRmVhdHVyZXMgPC0gdW5pcXVlKGMoYWxsRmVhdHVyZXMsIHJvd25hbWVzKGV4cHRzLmxzW1tteXJ1bl1dKSkpCn0KCmV4cHRzLmludGVncmF0ZWQubHMgPC0gbGlzdCgpCmZvciAobXlyZWdyZXNzIGluIHJlZ3Jlc3Npb24ydXNlKSB7CiAgIyBTZWxlY3QgbW9zdCB2YXJpYWJsZSBmZWF0dXJlcyBmb3IgaW50ZWdyYXRpb24KICBteWFzc2F5IDwtIGdzdWIoInJlZ3Jlc3MiLCAiU0NUIiwgbXlyZWdyZXNzKQogIG15ZmVhdHVyZXMgPC0gU2VsZWN0SW50ZWdyYXRpb25GZWF0dXJlcyhvYmplY3QubGlzdCA9IGV4cHRzLmxzLCBuZmVhdHVyZXMgPSBsZW5ndGgoYWxsRmVhdHVyZXMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdmYubmZlYXR1cmVzID0gYWxsRmVhdHVyZXMsIGFzc2F5ID0gcmVwKG15YXNzYXksIDQpKQogIAogICMgQ2FsY3VsYXRlIFBlYXJzb24gUmVzaWR1YWxzCiAgbXlpc28gPC0gUHJlcFNDVEludGVncmF0aW9uKG9iamVjdC5saXN0ID0gZXhwdHMubHMsIGFuY2hvci5mZWF0dXJlcyA9IG15ZmVhdHVyZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSwgYXNzYXkgPSByZXAobXlhc3NheSwgNCkpCiAgCiAgIyBJZGVudGlmeSBpbnRlZ3JhdGlvbiBhbmNob3JzCiAgcmVmIDwtIHdoaWNoKG5hbWVzKGV4cHRzLmxzKSA9PSBiYXNlbGluZSkKICBteS5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBteWlzbywgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiU0NUIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzYXkgPSByZXAobXlhc3NheSwgNCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZmVyZW5jZSA9IHJlZiwgc2NhbGUgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5jaG9yLmZlYXR1cmVzID0gbXlmZWF0dXJlcywgdmVyYm9zZSA9IFRSVUUpCiAgCiAgIyBJbnRlZ3JhdGUgc2VsZWN0ZWQgZGF0YQogIGludGVncmF0ZWROYW1lIDwtIHBhc3RlKCJJbnRlZ3JhdGVkIiwgbXlhc3NheSwgc2VwID0gIi4iKQogIG15aW50ZWdyYXRlZCA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IG15LmFuY2hvcnMsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIlNDVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IEZBTFNFLCBuZXcuYXNzYXkubmFtZSA9IGludGVncmF0ZWROYW1lKQogIAogIGV4cHRzLmludGVncmF0ZWQubHNbW215cmVncmVzc11dIDwtIG15aW50ZWdyYXRlZAp9CmBgYAoKIyMjIE9wdGlvbmFsbHkgUGxvdCBNaXNzaW5nIEZlYXR1cmVzCkxvc2UgfjI1MDAgZmVhdHVyZXMgKG9mIDE2OTkwKSBkdXJpbmcgaW50ZWdyYXRpb24KCmBgYHtyLCAicGxvdG1pc3NpbmdpbnRlZ3JhdGVkIixlY2hvPUZBTFNFfQppZiAoVFJVRSkgewogIGZvciAobXlyZWdyZXNzIGluIG5hbWVzKGV4cHRzLmludGVncmF0ZWQubHMpKSB7CiAgICBteWlzbyA8LSBleHB0cy5pbnRlZ3JhdGVkLmxzW1tteXJlZ3Jlc3NdXQogICAgbG9zdEZlYXQgPC0gcm93bmFtZXMobXlpc29AYXNzYXlzJFNDVC5EaWZmQGNvdW50cylbIShyb3duYW1lcyhteWlzb0Bhc3NheXMkU0NULkRpZmZAY291bnRzKSAlaW4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKG15aXNvQGFzc2F5cyRJbnRlZ3JhdGVkLlNDVC5EaWZmQGRhdGEpKV0KICAgIAogICAgY291bnRzLnBlci5mZWF0IDwtIGFwcGx5KG15aXNvQGFzc2F5cyRTQ1QuRGlmZkBjb3VudHMsIDEsIHN1bSkKICAgIGNlbGxzLnBlci5mZWF0IDwtIE1hdHJpeDo6cm93U3VtcyhteWlzb0Bhc3NheXMkU0NULkRpZmZAY291bnRzID4gMCkKICAgIAogICAgIyBQbG90IGNvdW50cyBhbmQgY2VsbHMgCiAgICBwbG90KHggPSBsb2cyKGNvdW50cy5wZXIuZmVhdCksIHkgPSBsb2cyKGNlbGxzLnBlci5mZWF0KSwgcGNoID0gMjAsIGNleCA9IDAuNSwKICAgICAgICAgeGxpbSA9IGMoMCwgMjUpLCB5bGltID0gYygyLCAxNCkpCiAgICBwb2ludHMoeCA9IGxvZzIoY291bnRzLnBlci5mZWF0W2xvc3RGZWF0XSksIHkgPSBsb2cyKGNlbGxzLnBlci5mZWF0W2xvc3RGZWF0XSksIHBjaCA9IDIwLCBjZXggPSAwLjUsIGNvbCA9ICJyZWQiKQogICAgCiAgICBwbG90KHggPSBsb2cyKGNvdW50cy5wZXIuZmVhdFtsb3N0RmVhdF0pLCB5ID0gbG9nMihjZWxscy5wZXIuZmVhdFtsb3N0RmVhdF0pLCBwY2ggPSAyMCwgY2V4ID0gMC41LCBjb2wgPSAicmVkIiwKICAgICAgICAgeGxpbSA9IGMoMCwgMjUpLCB5bGltID0gYygyLCAxNCkpCiAgICBwb2ludHMoeCA9IGxvZzIoY291bnRzLnBlci5mZWF0WyEobmFtZXMoY291bnRzLnBlci5mZWF0KSAlaW4lIGxvc3RGZWF0KV0pLAogICAgICAgICB5ID0gbG9nMihjZWxscy5wZXIuZmVhdClbIShuYW1lcyhjZWxscy5wZXIuZmVhdCkgJWluJSBsb3N0RmVhdCldLCBwY2ggPSAyMCwgY2V4ID0gMC41KQogICAgCiAgICBmb3IgKG15ZXhwdCBpbiBydW5zMnByb2Nlc3MpIHsKICAgICAgCiAgICB9CiAgICAKICB9Cn0KYGBgCgojIyMgUGxvdCBVTUFQIGFuZCBQQ0EKCmBgYHtyLCBlY2hvPUZBTFNFfQpmb3IgKG15ZmlsdCBpbiBuYW1lcyhleHB0cy5scykpIHsKICBmb3IgKG15cnVuIGluIG5hbWVzKGV4cHRzLmxzW1tteWZpbHRdXSkpIHsKICAgIGZvciAobXlyZWdyZXNzIGluIG5hbWVzKHJlZ3Jlc3Npb25zKSkgewogICAgICBteWFzc2F5IDwtIGlmZWxzZShteXJlZ3Jlc3MgPT0gIm5vcmVncmVzc2lvbiIsICJTQ1QiLCBnc3ViKCJyZWdyZXNzIiwgIlNDVCIsIG15cmVncmVzcykpCiAgICAgIG15cGNhIDwtIGdzdWIoIlNDVCIsICJwY2EiLCBteWFzc2F5KQogICAgICBwbG90KERpbVBsb3QoZXhwdHMubHNbW215ZmlsdF1dW1tteXJ1bl1dLCByZWR1Y3Rpb24gPSBteXBjYSkgICsgbGFicyh0aXRsZSA9IHNwcmludGYoIiVzOiAlcyIsIG15cnVuLCBteXJlZ3Jlc3MpKSkKICAgIAogICAgICBteXVtYXAgPC0gZ3N1YigiU0NUIiwgInVtYXAiLCBteWFzc2F5KQogICAgICBwbG90KERpbVBsb3QoZXhwdHMubHNbW215ZmlsdF1dW1tteXJ1bl1dLCByZWR1Y3Rpb24gPSBteXVtYXApICArIGxhYnModGl0bGUgPSBzcHJpbnRmKCIlczogJXMiLCBteXJ1biwgbXlyZWdyZXNzKSkpCiAgICB9CiAgfQp9CmBgYAoKIyMjIFNhdmUgdGhlIGRhdGEKCmBgYHtyLCBlY2hvPUZBTFNFfQojIFNhdmUgdGhlIGZpbGUKZm9yIChteWZpbHQgaW4gbmFtZXMoZXhwdHMubHMpKSB7CiAgZmlsZTJzYXZlIDwtIHNwcmludGYoImFtbF9ldG8ucmVncmVzc1NPLiVzLiVzLnJkcyIsIG15ZmlsdCwgU3lzLkRhdGUoKSkKICBwcmludChzcHJpbnRmKCIlcyBvYmplY3RzOiAgU2F2aW5nIHNjYWxlZC9ub3JtYWxpemVkL3JlZ3Jlc3NlZCBkYXRhIGluIGluZGl2aWR1YWwgb2JqZWN0cyBpbiAlcyIsIG15ZmlsdCwgZmlsZTJzYXZlKSkKICBzYXZlUkRTKGV4cHRzLmxzW1tteWZpbHRdXSwgZmlsZSA9IHBhc3RlKGRpcmVjdG9yeSRyZGEsIGZpbGUyc2F2ZSwgc2VwID0gIi8iKSkKfQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQpzZXNzaW9uSW5mbygpCmBgYAo=